
#ifndef __BUCKET_H__
#define __BUCKET_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "Constantes.h"

	typedef struct Elemento
	{
		TClave clave;
		void* dato;
	}Elemento;

	typedef struct Bucket
	{
		struct Elemento* elementos; //Se corresponde en posicion con longitudElemento, variable
		TLongElem* longitudElemento; //Se corresponde en posicion con elementos, variable
		unsigned int tamDispersion; //Tamanio de dispersion, se compara con tamanio de Tabla
		unsigned int cantElementos; //Cantidad de elementos contenidos en el Bucket
		unsigned int bytesLibres; //Espacio libre en el bucket
		unsigned int tamanioBucket; //Tamanio total de bucket (fijo)
		int nroBucket;
	}Bucket;

	/* -Inserta elemento en bucket. bucket pasa por referencia para devolverlo actualizado
	 * -Se inserta ordenado por clave
	 * PRECONDICION: 	-Validar que longitudElemento <= bucket.bytesLibres (segun 80%)
	 * 					-Ya se ha validado unicidad antes de llamarla
	 */
	int InsertarElementoBucket (Bucket* bucket, TClave clave, void* elemento, unsigned short int longitudElemento);

	/* Libera los elementos del Bucket.*/
	void liberarElementos(Elemento* elementos, unsigned int cantidad);

	/*Elimina elemento de bucket. 'bucket' pasa por referencia para devolverlo actualizado */
	int EliminarElementoBucket (Bucket* bucket, TClave clave);

	/*Devuele un elemento segun TClave, si no encuentra devuelve NULL*/
	void* ObtenerElementoBucket (Bucket bucket, TClave clave, unsigned int * tamanioElem);

	/*Busca la existencia del elemento por su clave en el bucket y devuelve OK en caso de q exista,
	 * de lo contrario devuelve ERROR
	 */
	int BuscarElementoBucket(Bucket* bucket, TClave clave);

	int ModificarElementoBucket(Bucket* bucket,TClave clave,void* elemento,unsigned int longElemento);

	/*Reserva Memoria, inicializa los campos*/
	Bucket* CrearBucket(unsigned int tamanioBucket);

	/* Guarda el bucket que recibe en la cadena de bytes que recibe */
	void BucketABytes (Bucket* bucket, char* bucketPersistente);

	/*Guarda el bucket en el archivo, 'bucket' debe tener el nroBloque asignado
	 */
	int GuardarBucket (FILE* archBloques, Bucket* bucket);

	/* Parsea la cadena de bytes que recibe en 'bucket' y carga el nuevoBucket.
	 * PRE: Bucket creado y con memoria alocada. Cargado el tamanio de Bucket.
	 */
	void CargarBucket(Bucket* nuevoBucket, char* bucket, unsigned int nroBucket);

	/*Libera toda la memoria asignada para 'bucket'*/
	void LiberarBucket (Bucket* bucket);

	/*Devuelve un bucket, obtenido a partir de la direccion (nroBucket * tamanioBucket) del archivo de datos, aqui se reserva memoria*/
	Bucket* LevantarBucket (FILE* archBloques, unsigned int nroBucket, unsigned int tamanioBucket);

	/*Debe llamarse antes de insertar un nuevo elemento, para verificar que no supere el 80% del espacio ocupado en el bloque*/
	int VerificarEspacioLibreEnBucket (Bucket bucket, TClave clave, unsigned int longElemento);

	void visualizarBucket(Bucket* bucket,FILE* salida);

	void visualizarElementosBucket(Bucket* bucket, FILE* salida);

	/* Devuelve un elemento y su clave segun el indice del vector de elementos. NULL si esta fuera de rango
	 * Pide memoria el elemento devuelto y la clave
	 * */
	void * ObtenerElementoByIndice(Bucket *bucket, unsigned int indice, TClave* claveDevuelta);



#endif /*__BUCKET_H__*/
